﻿using Abp.Authorization;
using Abp.AutoMapper;
using Abp.Linq.Extensions;
using Abp.Runtime.Session;
using RMM.Core.Cates;
using RMM.Core.Entity.Shops;
using RMM.Core.Evaluates;
using RMM.Core.Massagistes;
using RMM.Core.ShopService;
using RMM.Core.UserService;
using RMM.Evaluates.Dtos;
using RMM.FrameWork;
using RMM.ShopAppService.Dtos;
using RMM.Shops.Dtos;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RMM.ShopAppService
{
    //[AbpAuthorize]
    public class ShopAppService : IShopAppService
    {
        private readonly IShopService _shopService;
        private readonly IShopProjectService _shopProjectService;
        private readonly IUserService _userService;
        private readonly IEvaluateService _evaluateService;
        private readonly IEvaluateCateService _evaluateCateService;
        private readonly IMassagistService _massagistService;
        private readonly IMassagistExtendService _massagistExtendService;
        private readonly IMassagistProjectService _massagistProjectService;
        private readonly ICateService _cateService;

        public ShopAppService(IShopService shopService
            , IShopProjectService shopProjectService
            , IUserService userService
            , IEvaluateService evaluateService
            , IMassagistService massagistService
            , ICateService cateService
            , IMassagistExtendService massagistExtendService
            , IEvaluateCateService evaluateCateService
            , IMassagistProjectService massagistProjectService)
        {
            _shopService = shopService;
            _shopProjectService = shopProjectService;
            _userService = userService;
            _evaluateService = evaluateService;
            _massagistService = massagistService;
            _cateService = cateService;
            _massagistExtendService = massagistExtendService;
            _evaluateCateService = evaluateCateService;
            _massagistProjectService = massagistProjectService;
        }


        /// <summary>
        /// 获取店铺详情
        /// </summary>
        /// <param name="shopId"></param>
        /// <returns></returns>
        public async Task<ResultDto> GetShopByIdAsync(long shopId)
        {
            var shop = await _shopService.FirstOrDefaultAsync(shopId);
            if (shop == null)
            {
                return null;
            }
            var proj = (await _shopProjectService.GetAll()).Where(p => p.ShopId == shop.Id);
            var mass = await _massagistService.FirstOrDefaultAsync(p => p.ShopId == shop.Id);
            ShopArg arg = new ShopArg()
            {
                shopDto = shop.MapTo<ShopDto>(),
                shopProjectDto = proj.MapTo<List<ShopProjectDto>>(),
                Massagist = mass.MapTo<Massagists.Dtos.MassagistDto>()
            };

            return ResultDto.Success(arg);
        }

        /// <summary>
        /// 获取店铺列表
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<ResultDto> GetShopList(ShopInputDto dto)
        {
            var shop = await _shopService.GetAll();
            var shopProj = await _shopProjectService.GetAll();
            var massagist = await _massagistService.GetAll();
            var massExtend = await _massagistExtendService.GetAll();
            var evalCate = (await _evaluateCateService.GetAll())
                .Where(p=>p.Type == 1);
            var eval = (await _evaluateService.GetAll())
                .Where(p => p.ObjectType == 1);

            #region SqlWhere
            if (CommonHelper.Check(dto.AreaType))
            {
                if (CommonHelper.Check(dto.AreaId))
                {
                    shop.Concat(shop.WhereIf(dto.AreaType.Value == 0, p => p.ProvinceId == dto.AreaId)
                        .WhereIf(dto.AreaType.Value == 1, p => p.CityId == dto.AreaId));
                }
            }
            if (CommonHelper.Check(dto.CateId))
            {
                shopProj.Concat(shopProj.Where(p => p.CateId == dto.CateId));
            }
            if (CommonHelper.Check(dto.PriceStart) && CommonHelper.Check(dto.PriceEnd))
            {
                shopProj.Concat(shopProj.Where(p => p.Price <= dto.PageEnd.Value).Where(p => p.Price >= dto.PageStart.Value));
            }
            if (CommonHelper.Check(dto.Sex))
            {
                massagist.Concat(massagist.Where(p => p.Sex == dto.Sex));
            }
            if (CommonHelper.Check(dto.MassagitId))
            {
                massagist.Concat(massagist.Where(p => p.Id == dto.MassagitId));
            }
            #endregion

            var shopList = (from c in shop
                            join u in massagist on c.Id equals u.ShopId
                            join p in shopProj on c.Id equals p.ShopId
                            select new ShopDto
                            {
                                Address = c.Address,
                                ShopName = c.ShopName,
                                Id = c.Id,
                                _OpenBeginTime = c.OpenBeginTime,
                                _OpenEndTime = c.OpenEndTime,
                                Latitude = c.Latitude,
                                Longitude = c.Longitude,
                                Price = p.Price
                            }).ToList();

            shopList.ForEach(async p =>
            {
                List<int> cateList = eval.Where(x => x.ObjectId == p.Id).Select(s => s.CateList).FirstOrDefault()?.Split(',').Select(int.Parse).ToList();
                var mos = 0;
                try
                {
                    mos = eval.Where(x => x.ObjectId == p.Id).Sum(x => x.Star) / p.EvaluateNum;
                }
                catch
                {
                    mos = 0;
                }
                p.Evaluate = eval.Where(x => x.ObjectId == p.Id).OrderByDescending(x => x.CreationTime).FirstOrDefault().MapTo<EvaluateDto>();
                p.EvaluateNum = eval.Where(x => x.ObjectId == p.Id).OrderByDescending(x => x.CreationTime).Count();
                p.EvaluateCates = cateList == null ? new List<string>() : evalCate.WhereIf(cateList != null,e => cateList.Contains(e.Id)).Select(e => e.CateContent).ToList();
                p.MOS = mos;
                p.MakeNum = massExtend.Where(x => x.MassagistId == (massagist.Where(c => c.ShopId == p.Id).FirstOrDefault().Id) && x.Status == 0).Count();
                var str = string.Format("https://apis.map.qq.com/ws/distance/v1/?from={0},{1}&to={2},{3}&key=ZCQBZ-XTB34-OZEUE-XICUT-EY5ST-ZPB6Z", dto.lat, dto.lng, p.Latitude, p.Longitude);
                var data = await CommonHelper.GetAsync<ShopDistanceOutputJson>(str);
                p.rice = data.result.elements[0].distance;
            });
           

            Func<ShopDto, object> func = p => p.Id;

            if (CommonHelper.Check(dto.OrderType))
            {
                switch (dto.OrderType)
                {
                    case 0:
                        func = p => p.MOS;
                        break;
                    case 1:
                        func = p => p.rice;
                        break;
                    case 2:
                        func = p => p.MakeNum;
                        break;
                    case 3:
                        return ResultDto.Success(shopList.OrderBy(p => p.Price).Skip(dto.Skip * 10).Take(10).ToList());
                    case 4:
                        return ResultDto.Success(shopList.OrderByDescending(p => p.Price).Skip(dto.Skip * 10).Take(10).ToList());
                    default:
                        func = p => p.Id;
                        break;
                }
            }

            return ResultDto.Success(shopList.OrderByDescending(func).Skip(dto.Skip * 10).Take(10).ToList());
        }

        /// <summary>
        /// 获取范围店铺
        /// </summary>
        /// <param name="lat"></param>
        /// <param name="lng"></param>
        /// <param name="kilometer"></param>
        /// <param name="shops"></param>
        /// <returns></returns>
        public async Task<ResultDto> GetShopByDistance(double lat, double lng, int kilometer)
        {
            var jsonList = new List<ShopDistanceOutputJson>();
            var shops = (await _shopService.GetAll()).ToList();
            var eval = await _evaluateService.GetAll();
            foreach (var p in shops)
            {
                var str = string.Format("https://apis.map.qq.com/ws/distance/v1/?from={0},{1}&to={2},{3}&key=ZCQBZ-XTB34-OZEUE-XICUT-EY5ST-ZPB6Z", lat, lng, p.Latitude, p.Longitude);
                var data = await CommonHelper.GetAsync<ShopDistanceOutputJson>(str);
                data.shopId = p.Id;
                jsonList.Add(data);
            }
            jsonList = jsonList.Where(p => p.result.elements[0].distance <= kilometer).ToList();
            var list = await GetShopListA(jsonList.Select(p => p.shopId).ToList());
            foreach (var p in list)
            {
                p.Evaluate = eval.Where(x => x.ObjectId == p.Id).OrderByDescending(x => x.CreationTime).FirstOrDefault().MapTo<EvaluateDto>();
                p.EvaluateNum = eval.Where(x => x.ObjectId == p.Id).OrderByDescending(x => x.CreationTime).Count();
                var mos = 0;
                try
                {
                    mos = eval.Where(x => x.ObjectId == p.Id).Sum(x => x.Star) / p.EvaluateNum;
                }
                catch
                {
                    mos = 0;
                }
                p.MOS = mos;
            }
            return ResultDto.Success(list);
        }

        /// <summary>
        /// 快速下单获取最近的店铺
        /// </summary>
        /// <param name="lat"></param>
        /// <param name="lng"></param>
        /// <param name="projrctName"></param>
        /// <returns></returns>
        public async Task<ResultDto> GetOrderShopByDistance(double lat,double lng,int cateId)
        {
            var cate = await _cateService.FirstOrDefaultAsync(p => p.Id == cateId);
            var projList = await _shopProjectService.GetAll();
            var shopList = await _shopService.GetAll();
            var list = shopList.AsEnumerable()
                .Join(projList.AsEnumerable(), s => s.Id, p => p.ShopId, (s, p) => new Shop
                {
                    Id = s.Id,
                    Latitude = s.Latitude,
                    Longitude = s.Longitude
                })
                .ToList();
            var shop = (await GetShopByDistanceA(lat, lng, list)).Data as ShopDto;
            var arg = (await GetShopByIdAsync(shop.Id)).Data as ShopArg;
            arg.shopProjectDto = arg.shopProjectDto.Where(p => p.CateId == cateId).ToList();
            return ResultDto.Success(arg);
        }











        /// <summary>
        /// 获取最近的店铺 hiddenapi
        /// </summary>
        /// <param name="lat"></param>
        /// <param name="lng"></param>
        /// <param name="shops"></param>
        /// <returns></returns>
        public async Task<ResultDto> GetShopByDistanceA(double lat, double lng,List<Shop> shops)
        {
            var list = new List<long>();
            var jsonList = new List<ShopDistanceOutputJson>();
            foreach (var p in shops)
            {
                var str = string.Format("https://apis.map.qq.com/ws/distance/v1/?from={0},{1}&to={2},{3}&key=ZCQBZ-XTB34-OZEUE-XICUT-EY5ST-ZPB6Z", lat, lng, p.Latitude, p.Longitude);
                var data = await CommonHelper.GetAsync<ShopDistanceOutputJson>(str);
                data.shopId = p.Id;
                jsonList.Add(data);
            }
            var shopId = jsonList.OrderBy(p => p.result.elements.FirstOrDefault().distance).FirstOrDefault().shopId;
            return ResultDto.Success((await _shopService.FirstOrDefaultAsync(p => p.Id == shopId)).MapTo<ShopDto>());
        }

        /// <summary>
        /// 批量获取店铺列表by ids  hiddenapi
        /// </summary>
        /// <param name="shopIds"></param>
        /// <returns></returns>
        public async Task<List<ShopDto>> GetShopListA(List<long> shopIds)
        {
            var shops = (await _shopService.GetAll())
                .Where(p => shopIds.Contains(p.Id));
            var shopProj = await _shopProjectService.GetAll();
            var massagite = await _massagistService.GetAll();
            var eval = await _evaluateService.GetAll();

            var shopList = from c in shops
                           join u in massagite on c.Id equals u.ShopId
                           join p in shopProj on c.Id equals p.ShopId
                           select new ShopDto
                           {
                               Address = c.Address,
                               ShopName = c.ShopName,
                               Id = c.Id,
                               Latitude = c.Latitude,
                               Longitude = c.Longitude,
                               _OpenBeginTime = c.OpenBeginTime,
                               _OpenEndTime = c.OpenEndTime
                           };

            foreach (var p in shopList)
            {
                p.Evaluate = eval.Where(x => x.ObjectId == p.Id).OrderByDescending(x => x.CreationTime).FirstOrDefault().MapTo<EvaluateDto>();
                p.EvaluateNum = eval.Where(x => x.ObjectId == p.Id).OrderByDescending(x => x.CreationTime).Count();
            }

            return shopList.ToList();
        }
    }
}




